unit OrganizeGui;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ComCtrls, Menus,

  GlobalRecordsAndEnums,
  InventionCalc,
  Category, Items;

type
  TfrmOrganize = class(TForm)
    SidePanel: TPanel;
    btnClose: TButton;
    TreeView: TTreeView;
    gbUnassigned: TGroupBox;
    lstUnassigned: TListView;
    ButtonPanel: TPanel;
    btnCategory: TButton;
    lbl1: TLabel;
    lbl2: TLabel;
    lbl3: TLabel;
    TreeViewPopup: TPopupMenu;
    btnHelp: TButton;
    procedure btnCloseClick(Sender: TObject);
    procedure btnCategoryClick(Sender: TObject);
    procedure TreeViewPopupPopup(Sender: TObject);
    procedure TreeViewDragDrop(Sender, Source: TObject; X, Y: Integer);
    procedure TreeViewDragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    procedure btnHelpClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    inventionCalc: TInventionCalc;
    function GetNode(parent: TTreeNode; name: String): TTreeNode;
    procedure LoadUnassigned;

    procedure DeleteClick(Sender: TObject);
    procedure AddSubcategoryClick(Sender: TObject);
    procedure AddGroupClick(Sender: TObject);
  public
    constructor Create(AOwner: TComponent; invCalc: TInventionCalc); reintroduce;
  end;

var
  frmOrganize: TfrmOrganize;

implementation

{$R *.dfm}

uses
  StrUtils, ExtActns;

constructor TfrmOrganize.Create(AOwner: TComponent; invCalc: TInventionCalc);
var
  i, j, k: Integer;
  category: TCategory;
  subcategory: TSubcategory;
  group: TGroup;
  categorynode, subcategorynode, groupnode: TTreeNode;
//  item: TT1Item;
  item: TNewItem;
begin
  Inherited Create(AOwner);
  self.inventionCalc := invCalc;

  for i := 0 to inventionCalc.CategoryCount -1 do begin
    category := inventionCalc.GetCategory(i);
    categorynode := TreeView.Items.AddObject(nil, category.Name, category);
    for j := 0 to category.SubcategoryCount -1 do begin
      subcategory := category.GetSubcategory(j);
      subcategorynode := TreeView.Items.AddChildObject(categorynode, subcategory.Name, subcategory);
      for k := 0 to subcategory.GroupCount -1 do begin
        group := subcategory.GetGroup(k);
        TreeView.Items.AddChildObject(subcategorynode, group.Name, group);
      end;
    end;
  end;
//  for i := 0 to inventionCalc.T1ItemCount -1 do begin
  for i := 0 to inventionCalc.GetT1ItemCount -1 do begin
//    item := inventionCalc.GetT1Item(i);
    item := inventionCalc.GetT1ItemByIndex(i);
    if (item.Group <> nil) then begin
      categorynode := self.GetNode(nil, item.Category.Name);
      subcategorynode := self.GetNode(categorynode, item.Subcategory.Name);
      groupnode := self.GetNode(subcategorynode, item.Group.Name);
      TreeView.Items.AddChildObject(groupnode, item.Name, item);
    end
    else if (item.Subcategory <> nil) then begin
      categorynode := self.GetNode(nil, item.Category.Name);
      subcategorynode := self.GetNode(categorynode, item.Subcategory.Name);
      TreeView.Items.AddChildObject(subcategorynode, item.Name, item);
    end
    else if (item.Category <> nil) then begin
      categorynode := self.GetNode(nil, item.Category.Name);
      TreeView.Items.AddChildObject(categorynode, item.Name, item);
    end
    else begin
      lstUnassigned.AddItem(item.Name, item);
    end;

  end;
end;

procedure TfrmOrganize.btnCloseClick(Sender: TObject);
begin
  self.Close;
  self.Release;
end;

function TfrmOrganize.GetNode(parent: TTreeNode; name: String): TTreeNode;
var
  node: TTreeNode;
begin
  result := nil;
  node := nil;
  if (parent = nil) then begin
    node := TreeView.Items.GetFirstNode;
  end
  else if (parent.HasChildren) then begin
    node := parent.GetFirstChild;
  end;
  while (node <> nil) do begin
    if (node.Text = name) then begin
      result := node;
      break;
    end
    else node := node.GetNext;
  end;
end;

procedure TfrmOrganize.LoadUnassigned;
var
  i: Integer;
//  item: TT1item;
  item: TNewItem;
begin
  lstUnassigned.Clear;
//  for i := 0 to inventionCalc.T1ItemCount -1 do begin
  for i := 0 to inventionCalc.GetT1ItemCount -1 do begin
//    item := inventionCalc.GetT1Item(i);
    item := inventionCalc.GetT1ItemByIndex(i);
    if ((item.Group = nil) and (item.Subcategory = nil) and (item.Category = nil)) then begin
      lstUnassigned.AddItem(item.Name, item);
    end;
  end;
end;

procedure TfrmOrganize.TreeViewPopupPopup(Sender: TObject);
var
  classname: String;
  category: TCategory;
  subcategory: TSubcategory;
  group: TGroup;
//  t1item: TT1Item;
  t1item: TNewItem;
  item: TMenuItem;
begin
  if (TreeView.Selected <> nil) then begin
    classname := TObject(TreeView.Selected.Data).ClassName;
    TreeViewPopup.Items.Clear;
    if (classname = 'TCategory') then begin
      category := TCategory(TreeView.Selected.Data);

      item := TMenuItem.Create(TreeViewPopup);
      item.Caption := 'Delete';
      item.Name := 'piDelete_Category_' + IntToStr(category.ID);
      item.OnClick := DeleteClick;
      TreeViewPopup.Items.Add(item);
      item := TMenuItem.Create(TreeViewPopup);
      item.Caption := 'Add subcategory';
      item.Name := 'piAddSubcategory_' + IntToStr(category.ID);
      item.OnClick := AddSubcategoryClick;
      TreeViewPopup.Items.Add(item);
    end
    else if (classname = 'TSubcategory') then begin
      subcategory := TSubcategory(TreeView.Selected.Data);

      item := TMenuItem.Create(TreeViewPopup);
      item.Caption := 'Delete';
      item.Name := 'piDelete_Subcategory_' + IntToStr(subcategory.ID);
      item.OnClick := DeleteClick;
      TreeViewPopup.Items.Add(item);
      item := TMenuItem.Create(TreeViewPopup);
      item.Caption := 'Add group';
      item.Name := 'piAddgroup_' + IntToStr(subcategory.ID);
      item.OnClick := AddGroupClick;
      TreeViewPopup.Items.Add(item);
    end
    else if (classname = 'TGroup') then begin
      group := TGroup(TreeView.Selected.Data);

      item := TMenuItem.Create(TreeViewPopup);
      item.Caption := 'Delete';
      item.Name := 'piDelete_Group_' + IntToStr(group.ID);
      item.OnClick := DeleteClick;
      TreeViewPopup.Items.Add(item);
    end
     else if (classname = 'TNewItem') then begin
//      t1item := TT1Item(TreeView.Selected.Data);
      t1item := TNewItem(TreeView.Selected.Data);

      item := TMenuItem.Create(TreeViewPopup);
      item.Caption := 'Deassign';
      item.Name := 'piDelete_Item_' + IntToStr(t1item.ID);
      item.OnClick := DeleteClick;
      TreeViewPopup.Items.Add(item);
     end;
  end;
end;

procedure TfrmOrganize.DeleteClick(Sender: TObject);
var
  name: String;
  nodetype: String;
  category: TCategory;
  subcategory: TSubcategory;
  group: TGroup;
  t1item: TNewItem;
  i: Integer;
begin
  name := TMenuItem(Sender).Name;
  name := RightStr(name, Length(name) - Pos('_', name));
  nodetype := Leftstr(name, Pos('_', name) -1);
  if (TreeView.Selected <> nil) then begin
    if (nodetype = 'Category') then  begin
      category := TCategory(TreeView.Selected.Data);
      if (MessageDlg('Are you sure you want to delete the category "' + category.Name + '" and all related subcategories and groups?', mtWarning, [mbYes, mbNo], 0) = mrYes) then begin
        TreeView.Items.Delete(TreeView.Selected);
        inventionCalc.RemoveCategory(category);
        LoadUnassigned;
      end;
    end
    else if (nodetype = 'Subcategory') then begin
      subcategory := TSubcategory(TreeView.Selected.Data);
      if (MessageDlg('Are you sure you want to delete the subcategory "' + subcategory.Name + '" and all related groups?', mtWarning, [mbYes, mbNo], 0) = mrYes) then begin
        TreeView.Items.Delete(TreeView.Selected);
        inventionCalc.RemoveSubcategory(subcategory);
        LoadUnassigned;
      end;
    end
    else if (nodetype = 'Group') then begin
      group := TGroup(TreeView.Selected.Data);
      if (MessageDlg('Are you sure you want to delete the group "' + group.Name + '"?', mtWarning, [mbYes, mbNo], 0) = mrYes) then begin
        TreeView.Items.Delete(TreeView.Selected);
        inventionCalc.RemoveGroup(group);
        LoadUnassigned;
      end;
    end
    else if (nodetype = 'Item') then begin
  //    t1item := TT1Item(TreeView.Selected.Data);
      t1item := TNewItem(TreeView.Selected.Data);
      t1item.Category := nil;
      t1item.Subcategory := nil;
      t1item.Group := nil;
      for i := 0 to t1item.UsedInCount -1 do begin
        t1item.GetUsedIn(i).Item.Category := nil;
        t1item.GetUsedIn(i).Item.Subcategory := nil;
        t1item.GetUsedIn(i).Item.Group := nil;
      end;
      TreeView.Items.Delete(TreeView.Selected);
      lstUnassigned.AddItem(t1item.Name, t1item);
    end;
  end;
end;

procedure TfrmOrganize.FormDestroy(Sender: TObject);
begin
  inventionCalc.SaveCategories;
end;

procedure TfrmOrganize.btnCategoryClick(Sender: TObject);
var
  name: String;
  category: TCategory;
  i: Integer;
  allowedtoadd: Boolean;
begin
  if((InputQuery('Invention Calculator - Add category', 'Enter a name for the new category', name)) and (name <> '')) then begin
    allowedtoadd := true;
    for i := 0 to inventionCalc.CategoryCount -1 do begin
      if (inventionCalc.GetCategory(i).Name = name) then begin
        allowedtoadd := false;
        break;
      end;
    end;
    if (allowedtoadd) then begin
      category := inventionCalc.AddCategory(name);
      TreeView.Items.AddObject(nil, category.Name, category);
    end
    else MessageDlg('A category with name "' + name + '" already exists!', mtError, [mbOK], 0);
  end;
end;

procedure TfrmOrganize.btnHelpClick(Sender: TObject);
var
  run: TFileRun;
begin
  run := TFileRun.Create(self);
  run.FileName := 'help\Organize.html';
  run.Execute;
  run.Free;
end;

procedure TfrmOrganize.AddSubcategoryClick(Sender: TObject);
var
  name: String;
  i, id: Integer;
  category: TCategory;
  categorynode: TTreeNode;
  subcategory: TSubcategory;
  allowedtoadd: Boolean;
begin
  name := TMenuItem(Sender).Name;
  id := StrToInt(RightStr(name, Length(name) - Pos('_', name)));
  name := '';
  if((InputQuery('Invention Calculator - Add subcategory', 'Enter a name for the new subcategory', name)) and (name <> '')) then begin
    allowedtoadd := true;
    for i := 0 to inventionCalc.SubcategoryCount -1 do begin
      subcategory := inventionCalc.GetSubcategory(i);
      if ((subcategory.Name = name) and (subcategory.Category.ID = id)) then begin
        allowedtoadd := false;
        break;
      end;
    end;
    if (allowedtoadd) then begin
      category := inventionCalc.GetCategoryByID(id);
      categorynode := self.GetNode(nil, category.Name);
      subcategory := inventionCalc.AddSubcategory(name, category);
      TreeView.Items.AddChildObject(categorynode, name, subcategory);
      categorynode.Expand(false);
    end
    else MessageDlg('A category with name "' + name + '" already exists!', mtError, [mbOK], 0);
  end;
end;

procedure TfrmOrganize.AddGroupClick(Sender: TObject);
var
  name: String;
  i, id: Integer;
  category: TCategory;
  categorynode: TTreeNode;
  subcategory: TSubcategory;
  subcategorynode: TTreeNode;
  group: TGroup;
  allowedtoadd: Boolean;
begin
  name := TMenuItem(Sender).Name;
  id := StrToInt(RightStr(name, Length(name) - Pos('_', name)));
  name := '';
  if((InputQuery('Invention Calculator - Add group', 'Enter a name for the new group', name)) and (name <> '')) then begin
    allowedtoadd := true;
    for i := 0 to inventionCalc.GroupCount -1 do begin
      group := inventionCalc.GetGroup(i);
      if ((group.Name = name) and (group.Subcategory.ID = id)) then begin
        allowedtoadd := false;
        break;
      end;
    end;
    if (allowedtoadd) then begin
      subcategory := inventionCalc.GetSubCategoryByID(id);
      category := subcategory.Category;
      categorynode := self.GetNode(nil, category.Name);
      subcategorynode := self.GetNode(categorynode, subcategory.Name);
      group := inventionCalc.AddGroup(name, subcategory);
      TreeView.Items.AddChildObject(subcategorynode, name, group);
      subcategorynode.Expand(false);
    end
    else MessageDlg('A category with name "' + name + '" already exists!', mtError, [mbOK], 0);
  end;
end;

procedure TfrmOrganize.TreeViewDragOver(Sender, Source: TObject; X,
  Y: Integer; State: TDragState; var Accept: Boolean);
begin
  if ((Source.ClassName = 'TListView') and (TListView(Source).Name = 'lstUnassigned')) then
    Accept := true;
end;

procedure TfrmOrganize.TreeViewDragDrop(Sender, Source: TObject; X,
  Y: Integer);
var
  i: Integer;
  item: TNewItem;
  classname: String;
  subcategory: TSubcategory;
  group: TGroup;
begin
  TreeView.Selected := TreeView.GetNodeAt(X, Y);
  item := TNewItem(lstUnassigned.Selected.Data);
  if ((TreeView.Selected <> nil) and (TObject(TreeView.Selected.Data).ClassName <> 'TNewItem')) then begin
    lstUnassigned.DeleteSelected;
    TreeView.Items.AddChildObject(TreeView.Selected, item.Name, item);
    TreeView.Selected.Expand(false);
    classname := TObject(TreeView.Selected.Data).ClassName;
    if (classname = 'TCategory') then begin
      item.Category := TCategory(TreeView.Selected.Data);
      item.Subcategory := nil;
      item.Group := nil;
      for i := 0 to item.UsedInCount -1 do begin
        item.GetUsedIn(i).Item.Category := TCategory(TreeView.Selected.Data);
        item.GetUsedIn(i).Item.Subcategory := nil;
        item.GetUsedIn(i).Item.Group := nil;
      end;
    end
    else if (classname = 'TSubcategory') then begin
      subcategory := TSubCategory(TreeView.Selected.Data);
      item.Category := subcategory.Category;
      item.Subcategory := subcategory;
      item.Group := nil;
      for i := 0 to item.UsedInCount -1 do begin
        item.GetUsedIn(i).Item.Category := subcategory.Category;
        item.GetUsedIn(i).Item.Subcategory := subcategory;
        item.GetUsedIn(i).Item.Group := nil;
      end;
    end
    else if (classname = 'TGroup') then begin
      group := TGroup(TreeView.Selected.Data);
      item.Category := group.Subcategory.Category;
      item.Subcategory := group.Subcategory;
      item.Group := group;
      for i := 0 to item.UsedInCount -1 do begin
        item.GetUsedIn(i).Item.Category := group.Subcategory.Category;;
        item.GetUsedIn(i).Item.Subcategory := group.Subcategory;
        item.GetUsedIn(i).Item.Group := group;
      end;
    end;
  end;
  TreeView.Repaint;
end;

end.
